package com.dhl.fin.api.service;

import cn.hutool.http.HttpRequest;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.dhl.fin.api.common.config.WebConfig;
import com.dhl.fin.api.common.dto.QueryDto;
import com.dhl.fin.api.common.service.CommonService;
import com.dhl.fin.api.common.util.JsonUtil;
import com.dhl.fin.api.common.util.MapUtil;
import com.dhl.fin.api.common.util.ObjectUtil;
import com.dhl.fin.api.common.util.WebUtil;
import com.dhl.fin.api.dao.MyRemindDao;
import com.dhl.fin.api.domain.LoginAccount;
import com.dhl.fin.api.dto.LoginDTO;
import com.dhl.fin.api.dto.WeiXinLoginDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author CuiJianbo
 * @since 2025/3/16
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class LoginAccountService extends CommonService<LoginAccount> {

    @Value("${custom.appId}")
    private String appId;

    @Value("${custom.secret}")
    private String secret;

    @Value("${custom.url}")
    private String url;

    @Autowired
    private WebConfig webConfig;

    @Autowired
    private MyRemindDao myRemindDao;

    public Map login(LoginDTO loginDTO) throws Exception {

        WeiXinLoginDTO weiXinLoginDTO = weixinLogin(loginDTO.getCode());
        String openId = weiXinLoginDTO.getOpenId();
        String sessionKey = weiXinLoginDTO.getSessionKey();
//        boolean isNewUser = remindTaskService.isNewUser(openId);
        LoginAccount loginAccount = get(QueryDto.builder()
                .available()
                .addWhere(String.format("open_idd='%s'", openId))
                .build());
        if (ObjectUtil.isNull(loginAccount)) {
            //创建新的账号
            save(LoginAccount.getInstance(openId, sessionKey));
        } else {
            //更新sessionKey和loginTime
            updateBySelective(loginAccount.getUpdateInstance(sessionKey));
        }

        return MapUtil.builder()
                .add("unicode", openId)
                .add("token", generateToken(openId))
                .build();

    }

    public WeiXinLoginDTO weixinLogin(String code) {
        String finalUrl = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", url, appId, secret, code);
        String jsonData = HttpRequest.get(finalUrl).execute().body();
        Map responseData = JsonUtil.parseToMap(jsonData);
        String openId = MapUtil.getString(responseData, "openid");
        String sessionKey = MapUtil.getString(responseData, "session_key");
        log.info("在微信服务器上登录成功返回数据-> {}", jsonData);

        return WeiXinLoginDTO.builder()
                .openId(openId)
                .sessionKey(sessionKey)
                .build();
    }

    /**
     * 根据openId生成token
     *
     * @param openId
     * @return
     * @throws UnsupportedEncodingException
     */
    private String generateToken(String openId) throws UnsupportedEncodingException {
        Map headerClaims = MapUtil.builder()
                .add("uuid", openId)
                .add("name", "用户")
                .add("mail", "")
                .add("adminType", "")
                .build();
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(11, this.webConfig.userTokenExpiredAfterHours);
        String token = JWT.create()
                .withHeader(headerClaims)
                .withExpiresAt(cal.getTime())
                .sign(Algorithm.HMAC256(this.webConfig.tokenKey));
        return token;
    }

    public void increaseAllowCount(String openId) {
        myRemindDao.increaseCount(openId);
    }

    public void resetAllowCount(String openId) throws Exception {
        LoginAccount loginAccount = new LoginAccount();
        loginAccount.setAllowCount(0);
        updateBySelective(loginAccount, QueryDto.builder()
                .available()
                .addWhere("open_idd='" + openId + "'")
                .build());
    }

    public void subAllowCount(String openId) {
        myRemindDao.subCount(openId);
    }

    public Integer getAccountAllowCount() throws Exception {
        String openId = WebUtil.getLoginUser().getUuid();
        return get(QueryDto.builder()
                .available()
                .addWhere(String.format("open_idd='%s'", openId))
                .build()).getAllowCount();
    }

    public List<LoginAccount> getAccountsOfWillStop() {
        return myRemindDao.findRemindCountUser();
    }

}
